home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 326-350 / disk_333 / multiplot / source / mplot_src / color.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  29KB  |  885 lines

  1.  
  2. /* *** color.c *************************************************************
  3.  *
  4.  * ColorWindow Routine  --  Color Window Routines
  5.  *     from Book 1 of the Amiga Programmers' Suite by RJ Mical
  6.  *
  7.  * Copyright (C) 1986, 1987, Robert J. Mical
  8.  * All Rights Reserved.
  9.  *
  10.  * Created for Amiga developers.
  11.  * Any or all of this code can be used in any program as long as this
  12.  * entire copyright notice is retained, ok?  Thanks.
  13.  *
  14.  * The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable.
  15.  * All copyright notices and all file headers must be retained intact.
  16.  * The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the
  17.  * resultant object code may be included in any software product.  However, no
  18.  * portion of the source listings or documentation of the Amiga Programmer's
  19.  * Suite Book 1 may be distributed or sold for profit or in a for-profit
  20.  * product without the written authorization of the author, RJ Mical.
  21.  *
  22.  * HISTORY      NAME            DESCRIPTION
  23.  * -----------  --------------  --------------------------------------------
  24.  * 20 Oct 87    - RJ            Make the window draggable
  25.  * 3 Jan 87     RJ >:-{)*       Clean-up for release
  26.  * 27 Feb 86    =RJ Mical=      Modified these routines for Zaphod
  27.  * January 86   =RJ=            Modified the originals for Mandelbrot
  28.  * Late 85      =RJ=            Created the color window for Graphicraft
  29.  *
  30.  * *********************************************************************** */
  31.  
  32.  
  33. #include "color.h"
  34.  
  35.  
  36.  
  37. extern struct Gadget ColorTemplateGadgets[COLOR_GADGETS_COUNT];
  38. extern struct Image ColorPropsImages[3];
  39. extern struct PropInfo ColorPropsInfos[3];
  40. extern struct Image ColorRGBImage;
  41. extern struct Image ColorHSLImage;
  42. extern struct Image SuperColorImages[32];
  43.  
  44. UBYTE *AllocRemember();
  45. struct IntuiMessage *GetMsg();
  46. struct Window *OpenWindow();
  47.  
  48.  
  49.  
  50. /* ColorMode definitions */
  51. #define COPYCOLOR       1
  52. #define RANGE_FIRST  2
  53. #define RANGE_SECOND 3
  54.  
  55. /* These are the dimensions of the color hit box */
  56. #define COLOR_COLOR_ROWS        (4 * 10)
  57. #define COLOR_COLOR_COLS        (8 * 15)
  58. #define COLOR_COLOR_RIGHT   (COLOR_BOX_LEFT + COLOR_COLOR_COLS - 1)
  59. #define COLOR_COLOR_BOTTOM  (COLOR_COLOR_TOP + COLOR_COLOR_ROWS - 1)
  60.  
  61. VOID ResetColorProps();
  62.  
  63.  
  64. struct NewWindow ColorNewWindow =
  65.         {
  66.         /*              SHORT LeftEdge, TopEdge;                /* screen dimensions of window */
  67.         /*              SHORT Width, Height;                            /* screen dimensions of window */
  68.         20, 12,
  69.         COLORWINDOW_WIDTH, COLORWINDOW_HEIGHT,
  70.  
  71.         /*              UBYTE DetailPen, BlockPen;              /* for bar/border/gadget rendering */
  72.         -1, -1,
  73.  
  74.         /*              ULONG IDCMPFlags;                               /* User-selected IDCMP flags */
  75.         GADGETDOWN | GADGETUP | MOUSEBUTTONS
  76.                         | MENUPICK | MOUSEMOVE | ACTIVEWINDOW | INACTIVEWINDOW,
  77.  
  78.         /*              ULONG Flags;                                            /* see Window struct for defines */
  79.         WINDOWDRAG | SMART_REFRESH | NOCAREREFRESH | ACTIVATE,
  80.  
  81.         /*              struct Gadget *FirstGadget;*/
  82.         &ColorTemplateGadgets[COLOR_GADGETS_COUNT - 1],
  83.  
  84.         /*              struct Image *CheckMark;*/
  85.         NULL,
  86.  
  87.         /*              UBYTE *Title;                                             /* the title text for this window */
  88.         (UBYTE *)"Change Colors",
  89.  
  90.         /*              struct Screen *Screen;*/
  91.         NULL,
  92.  
  93.         /*              struct BitMap *BitMap;*/
  94.         NULL,
  95.  
  96.         /*              SHORT MinWidth, MinHeight;               /* minimums */
  97.         0, 0,
  98.         /*              SHORT MaxWidth, MaxHeight;               /* maximums */
  99.         0, 0,
  100.  
  101.         /*              USHORT Type;*/
  102.         CUSTOMSCREEN,
  103. };
  104.  
  105. USHORT ColorMode;
  106. USHORT RangeFirst;
  107. struct Window *ColorWindow = NULL;
  108. struct RastPort *ColorRPort;
  109. struct ViewPort *ColorVPort;
  110. SHORT RowCount, RowHeight, ColumnCount, ColumnWidth;
  111. USHORT SavePalette[32];
  112.  
  113.  
  114.  
  115.  
  116. /* ======================================================================= */
  117. /* === These Routines Open, Render, and Close the Color Window =========== */
  118. /* ======================================================================= */
  119.  
  120. VOID InitColorSizes(depth)
  121. SHORT depth;
  122. /* This routine adjusts the row and column variables based on the number
  123.  * of colors supported by the ColorWindow's screen.
  124.  */
  125. {
  126.         RowCount = 1 << (depth >> 1);
  127.         RowHeight = COLOR_COLOR_ROWS / RowCount;
  128.  
  129.         ColumnCount = 1 << ((depth + 1) >> 1);
  130.         ColumnWidth = COLOR_COLOR_COLS / ColumnCount;
  131. }
  132.  
  133.  
  134.  
  135. VOID DrawBox(rp, left, top, right, bottom)
  136. struct RastPort *rp;
  137. SHORT left, top, right, bottom;
  138. /* A quick utility routine */
  139. {
  140.         SHORT savepen;
  141.  
  142.         savepen = ColorRPort->FgPen;
  143.  
  144.         SetAPen(rp, 1);
  145.         SetDrMd(rp, JAM2);
  146.  
  147.         Move(rp, left, top);
  148.         Draw(rp, left, bottom);
  149.         Draw(rp, right, bottom);
  150.         Draw(rp, right, top);
  151.         Draw(rp, left, top);
  152.  
  153.         SetAPen(ColorRPort, savepen);
  154. }
  155.  
  156.  
  157.  
  158. VOID ColorRectFill(pen)
  159. SHORT pen;
  160. /* This routine sets the pen in the RastPort as the current pen selected
  161.  * by the user, and then fills the color box with that pen color.
  162.  */
  163. {
  164.         SetAPen(ColorRPort, pen);
  165.         SetDrMd(ColorRPort, JAM1);
  166.         RectFill(ColorRPort, COLOR_BOX_LEFT, COLOR_BOX_TOP,
  167.                 COLOR_BOX_RIGHT, COLOR_BOX_BOTTOM);
  168. }
  169.  
  170.  
  171.  
  172. VOID DrawColorWindow()
  173. /* This routine fills in all the graphic details of the ColorWindow */
  174. {
  175.         SHORT col, row, colstart, colend, rowstart;
  176.         SHORT savepen;
  177.  
  178.         savepen = ColorRPort->FgPen;
  179.  
  180.         InitColorSizes(ColorRPort->BitMap->Depth);
  181.  
  182.         ColorRectFill(ColorRPort->FgPen);
  183. /*???   DrawBox(ColorRPort, 1, 1, COLORWINDOW_WIDTH - 2, COLORWINDOW_HEIGHT - 2);*/
  184.         DrawBox(ColorRPort, COLOR_BOX_LEFT - 2, COLOR_BOX_TOP - 2,
  185.                         COLOR_BOX_RIGHT + 2, COLOR_BOX_BOTTOM + 2);
  186.         DrawBox(ColorRPort, COLOR_BOX_LEFT - 2, COLOR_COLOR_TOP - 2,
  187.                         COLOR_BOX_LEFT + (8 * 15) + 1, COLOR_COLOR_TOP + (4 * 10) + 1);
  188.  
  189.         colstart = COLOR_BOX_LEFT;
  190.         colend = colstart + ColumnWidth - 1;
  191.         for (col = 0; col < ColumnCount; col++)
  192.                 {
  193.                 rowstart = COLOR_COLOR_TOP;
  194.                 for (row = 0; row < RowCount; row++)
  195.                         {
  196.                         SetAPen(ColorRPort, (row * ColumnCount) + col);
  197.                         RectFill(ColorRPort, colstart, rowstart, colend,
  198.                                         rowstart + RowHeight - 1);
  199.                         rowstart += RowHeight;
  200.                         }
  201.                 colstart += ColumnWidth;
  202.                 colend += ColumnWidth;
  203.                 }
  204.  
  205.         SetAPen(ColorRPort, savepen);
  206. }
  207.  
  208.  
  209.  
  210.  
  211. struct Window *OpenColorWindow(screen, firstpen)
  212. struct Screen *screen;
  213. SHORT firstpen;
  214. {
  215.         SHORT i;
  216.  
  217.         if (ColorNewWindow.Screen = screen) ColorNewWindow.Type = CUSTOMSCREEN;
  218.         else ColorNewWindow.Type = WBENCHSCREEN;
  219.  
  220.         if ((ColorWindow = OpenWindow(&ColorNewWindow)) == 0) return(NULL);
  221.  
  222.         ColorVPort = &ColorWindow->WScreen->ViewPort;
  223.         ColorRPort = ColorWindow->RPort;
  224.  
  225.         for (i = 0; i < 32; i++)
  226.                 SavePalette[i] = GetRGB4(ColorVPort->ColorMap, i);
  227.  
  228.         SetAPen(ColorRPort, firstpen);
  229.         ResetColorProps();
  230.         DrawColorWindow();
  231.  
  232.         ColorMode = NULL;
  233.  
  234.         return(ColorWindow);
  235. }
  236.  
  237.  
  238.  
  239.  
  240. VOID CloseColorWindow(accept)
  241. BOOL accept;
  242. {
  243.         if (ColorWindow == NULL) return;
  244.  
  245.         if (NOT accept) LoadRGB4(ColorVPort, &SavePalette[0], 32);
  246.  
  247.         CloseWindow(ColorWindow);
  248.         ColorWindow = NULL;
  249. }
  250.  
  251.  
  252.  
  253.  
  254. /* ======================================================================= */
  255. /* === These Routines Manage the User Interaction ======================== */
  256. /* ======================================================================= */
  257.  
  258. BOOL ColorGadgetGotten(gadget)
  259. struct Gadget *gadget;
  260. /* This routine manages the user's gadget selection.  If one of the
  261.  * end gadgets, such as OK or CANCEL, was selected then this routine
  262.  * returns FALSE, else it returns TRUE.
  263.  */
  264. {
  265.         switch (gadget->GadgetID)
  266.                 {
  267.                 case COLOR_OK:
  268.                         CloseColorWindow(TRUE);
  269.                         return(FALSE);
  270.                         break;
  271.                 case COLOR_CANCEL:
  272.                         CloseColorWindow(FALSE);
  273.                         return(FALSE);
  274.                         break;
  275.                 case COLOR_COPY:
  276.                         ColorMode = COPYCOLOR;
  277.                         break;
  278.                 case COLOR_RANGE:
  279.                         ColorMode = RANGE_FIRST;
  280.                         break;
  281.                 case COLOR_HSL_RGB:
  282.                         ResetColorProps();
  283.                         break;
  284.                 }
  285.         return(TRUE);
  286. }
  287.  
  288.  
  289.  
  290. VOID ColorRange(first, last)
  291. SHORT first, last;
  292. /* Create the color range from first to last */
  293. {
  294.         SHORT i;
  295.         SHORT whole, redfraction, greenfraction, bluefraction, divisor;
  296.         USHORT rgb;
  297.         SHORT firstred, firstgreen, firstblue;
  298.         SHORT lastred, lastgreen, lastblue;
  299.         SHORT workred, workgreen, workblue;
  300.  
  301.         /* If the pen numbers are out of order, swap */
  302.         if (first > last)
  303.                 {
  304.                 i = first;
  305.                 first = last;
  306.                 last = i;
  307.                 }
  308.  
  309.         /* I need to see a spread of at least two, where there's at least one
  310.          * spot between the endpoints, else there's no work to do so I
  311.          * might as well just return now.
  312.          */
  313.         if (first >= last - 1) return;
  314.  
  315.         rgb = GetRGB4(ColorVPort->ColorMap, first);
  316.         firstred = (rgb >> 8) & 0xF;
  317.         firstgreen = (rgb >> 4) & 0xF;
  318.         firstblue = (rgb >> 0) & 0xF;
  319.  
  320.         rgb = GetRGB4(ColorVPort->ColorMap, last);
  321.         lastred = (rgb >> 8) & 0xF;
  322.         lastgreen = (rgb >> 4) & 0xF;
  323.         lastblue = (rgb >> 0) & 0xF;
  324.  
  325.  
  326.         divisor = last - first;
  327.  
  328.         /* Do all math as fixed-point fractions where the low 8 bits are
  329.          * the fraction.  This greatly lessens the effect of rounding errors.
  330.          */
  331.         whole = (lastred - firstred) << 8;
  332.         redfraction = whole / divisor;
  333.  
  334.         whole = (lastgreen - firstgreen) << 8;
  335.         greenfraction = whole / divisor;
  336.  
  337.         whole = (lastblue - firstblue) << 8;
  338.         bluefraction = whole / divisor;
  339.  
  340.         for (i = first + 1; i < last; i++)
  341.                 {
  342.                 lastred = ((redfraction * (i - first)) + 0x0080) >> 8;
  343.                 workred = firstred + lastred;
  344.                 lastgreen = ((greenfraction * (i - first)) + 0x0080) >> 8;
  345.                 workgreen = firstgreen + lastgreen;
  346.                 lastblue = ((bluefraction * (i - first)) + 0x0080) >> 8;
  347.                 workblue = firstblue + lastblue;
  348.                 SetRGB4(ColorVPort, i, workred, workgreen, workblue);
  349.                 }
  350. }
  351.  
  352.  
  353.  
  354.  
  355. VOID ColorWindowHit(x, y)
  356. SHORT x, y;
  357. /* The color boxes at the bottom-right of the ColorWindow are not gadgets.
  358.  * Instead, it's just graphics and this routine is used to detect whether
  359.  * the user has selected one of the color boxes.
  360.  */
  361. {
  362.         USHORT rgb, pen;
  363.  
  364.         /* Have we got a color specifier? */
  365.         if ( (x >= COLOR_BOX_LEFT) && (x <= COLOR_COLOR_RIGHT)
  366.                         && (y >= COLOR_COLOR_TOP) && (y <= COLOR_COLOR_BOTTOM) )
  367.                 {
  368.                 /* Yes, it's one of the color boxes.  Set this pen number */
  369.                 x = x - COLOR_BOX_LEFT;
  370.                 x = x / ColumnWidth;
  371.                 y = y - COLOR_COLOR_TOP;
  372.                 y = y / RowHeight;
  373.                 pen = (y * ColumnCount) + x;
  374.  
  375.                 /* first, were we in COPY COLOR mode? */
  376.                 if (ColorMode == COPYCOLOR)
  377.                         {
  378.                         /* ok, copy old color here first! */
  379.                         rgb = GetRGB4(ColorVPort->ColorMap, ColorRPort->FgPen);
  380.                         SetRGB4(ColorVPort, pen, rgb >> 8, rgb >> 4, rgb);
  381.                         ColorMode = NULL;
  382.                         }
  383.                 else if (ColorMode == RANGE_FIRST)
  384.                         {
  385.                         ColorMode = RANGE_SECOND;
  386.                         RangeFirst = pen;
  387.                         }
  388.                 else if (ColorMode == RANGE_SECOND)
  389.                         {
  390.                         ColorMode = NULL;
  391.                         ColorRange(RangeFirst, pen);
  392.                         }
  393.                 ColorRectFill(pen);
  394.  
  395.                 ResetColorProps();
  396.                 }
  397. }
  398.  
  399.  
  400.  
  401. VOID SetPropValueGrunt(value, y)
  402. SHORT value, y;
  403. {
  404.         UBYTE text[16];
  405.  
  406.         if (value >= 0) sprintf(&text[0], "%ld ", value);
  407.         else
  408.                 {
  409.                 text[0] = ' ';
  410.                 text[1] = ' ';
  411.                 }
  412.  
  413.         Move(ColorRPort, COLOR_VALUE_X, y);
  414.         Text(ColorRPort, &text[0], 2);
  415. }
  416.  
  417.  
  418.  
  419. VOID SetPropValues(red, green, blue)
  420. SHORT red, green, blue;
  421. /* Sets the text to the right of the prop gadgets */
  422. {
  423.         SHORT savepen;
  424.  
  425.         savepen = ColorRPort->FgPen;
  426.  
  427.         SetAPen(ColorRPort, 1);
  428.         SetDrMd(ColorRPort, JAM2);
  429.  
  430.         SetPropValueGrunt(red, COLOR_VALUE_REDY);
  431.         SetPropValueGrunt(green, COLOR_VALUE_GREENY);
  432.         SetPropValueGrunt(blue, COLOR_VALUE_BLUEY);
  433.  
  434.         SetAPen(ColorRPort, savepen);
  435. }
  436.  
  437.  
  438.  
  439. VOID ModifyRGBColors()
  440. {
  441.         USHORT newred, newgreen, newblue;
  442.  
  443.         newred = ColorPropsInfos[0].HorizPot >> 12;
  444.         newgreen = ColorPropsInfos[1].HorizPot >> 12;
  445.         newblue = ColorPropsInfos[2].HorizPot >> 12;
  446.  
  447.         SetRGB4(ColorVPort, ColorRPort->FgPen, newred, newgreen, newblue);
  448.         SetPropValues(newred, newgreen, newblue);
  449. }
  450.  
  451.  
  452.  
  453.  
  454. VOID ModifyHSLColors()
  455. {
  456.         USHORT rgb;
  457.         SHORT HSLToRGB();
  458.  
  459.         rgb = (USHORT)HSLToRGB(
  460.                         ColorPropsInfos[0].HorizPot,
  461.                         ColorPropsInfos[1].HorizPot,
  462.                         ColorPropsInfos[2].HorizPot);
  463.  
  464.         SetRGB4(ColorVPort, ColorRPort->FgPen, rgb >> 8, rgb >> 4, rgb);
  465.         SetPropValues(-1, -1, -1);
  466. }
  467.  
  468.  
  469.  
  470.  
  471. VOID ModifyColors()
  472. /* This routine reacts to the user playing with one of the prop gadgets */
  473. {
  474.         if (ColorTemplateGadgets[COLOR_HSL_RGB].Flags & SELECTED)
  475.                 ModifyHSLColors();
  476.         else
  477.                 ModifyRGBColors();
  478. }
  479.  
  480.  
  481.  
  482. VOID SetRGBProps(rgb)
  483. USHORT rgb;
  484. {
  485.         USHORT red, green, blue;
  486.  
  487.         red = (rgb >> 8) & 0xF;
  488.         green = (rgb >> 4) & 0xF;
  489.         blue = (rgb >> 0) & 0xF;
  490.  
  491.         ColorPropsInfos[0].HorizPot
  492.                         = (red << 12) | (red << 8) | (red << 4) | red;
  493.         ColorPropsInfos[1].HorizPot
  494.                         = (green << 12) | (green << 8) | (green << 4) | green;
  495.         ColorPropsInfos[2].HorizPot
  496.                         = (blue << 12) | (blue << 8) | (blue << 4) | blue;
  497.  
  498.         SetPropValues(red, green, blue);
  499. }
  500.  
  501.  
  502.  
  503. VOID SetHSLProps(rgb)
  504. USHORT rgb;
  505. {
  506. VOID RGBToHSL();
  507.  
  508.         RGBToHSL(rgb,
  509.                         &ColorPropsInfos[0].HorizPot,
  510.                         &ColorPropsInfos[1].HorizPot,
  511.                         &ColorPropsInfos[2].HorizPot);
  512.  
  513.         SetPropValues(-1, -1, -1);
  514. }
  515.  
  516.  
  517.  
  518. VOID ResetColorProps()
  519. /* This routine resets the proportional gadgets according to the current
  520.  * pen number and the interaction technique
  521.  */
  522. {
  523.         SHORT bluepos;
  524.         USHORT rgb;
  525.  
  526.         rgb = GetRGB4(ColorVPort->ColorMap, ColorRPort->FgPen);
  527.  
  528.         bluepos = RemoveGList(ColorWindow, &ColorTemplateGadgets[COLOR_BLUE], 3);
  529.  
  530.         if (ColorTemplateGadgets[COLOR_HSL_RGB].Flags & SELECTED)
  531.                 SetHSLProps(rgb);
  532.         else SetRGBProps(rgb);
  533.  
  534.         AddGList(ColorWindow, &ColorTemplateGadgets[COLOR_BLUE], bluepos, 3, 0);
  535.         RefreshGList(&ColorTemplateGadgets[COLOR_BLUE], ColorWindow, NULL, 3);
  536. }
  537.  
  538.  
  539.  
  540.  
  541.  
  542. /* ======================================================================= */
  543. /* === And finally, the Main Entry Point ================================= */
  544. /* ======================================================================= */
  545.  
  546.  
  547. /* *** DoColorWindow() ******************************************************
  548.  *
  549.  * NAME
  550.  *     DoColorWindow  --  Allows the user to change a screen's colors
  551.  *
  552.  *
  553.  * SYNOPSIS
  554.  *     BOOL DoColorWindow(Screen, Left, Top, FirstPen, UseRGB);
  555.  *
  556.  *
  557.  * FUNCTION
  558.  *     This routine creates a window, called the ColorWindow, which has
  559.  *     gadgets that allow the user to change the colors of any screen.
  560.  *     After opening the ColorWindow, this routine interacts with the
  561.  *     user until the user is satisfied with the current colors, at which
  562.  *     time the window is closed and control is returned to you.
  563.  *
  564.  *     The ColorWindow will open in the specified Screen.  The Screen
  565.  *     argument can be equal to NULL; if it is, the ColorWindow will be
  566.  *     opened in the Workbench screen.  The ColorWindow automatically
  567.  *     adapts itself to any screen.
  568.  *
  569.  *     With the Top and Left arguments you specify the position of the
  570.  *     ColorWindow's top-left corner.  Note that no position-error
  571.  *     checking is done, so you must take care to not place the window
  572.  *     outside of the bounds of your screen.  Currently, the Left argument
  573.  *     can range from 0 to 88 on low-resolution screens, and 0 to 408
  574.  *     on high-resolution screens.  The Top argument can range from
  575.  *     0 to 109 on a 200-line screen, and 0 to 309 on an interlaced screen.
  576.  *     These figures don't include overscan, which most programmers
  577.  *     don't use.  The width and height of the ColorWindow are defined
  578.  *     by the constants COLORWINDOW_WIDTH and COLORWINDOW_HEIGHT in the
  579.  *     color.h file.
  580.  *
  581.  *     The FirstPen argument is used to initialize the color that's
  582.  *     displayed when the ColorWindow is first created.
  583.  *
  584.  *     The ColorWindow is capable of allowing the user to modify the
  585.  *     colors using either an RGB or an HSL technique.  The RGB technique
  586.  *     involves three proportional gadgets, one for each of Red, Green
  587.  *     and Blue.  By adjusting one of these gadgets, the user adjusts
  588.  *     the amount of the associated color component in the final color.
  589.  *     Some people feel that this is the most intuitive way to change
  590.  *     colors on the Amiga, as this is how colors are represented
  591.  *     internally by the Amiga.  The other technique, HSL, allows the
  592.  *     user to adjust the Hue, Saturation and Luminance of the final color.
  593.  *     Some people feel that *this* is the most intuitive way for users
  594.  *     to change color, because it's based on color theory and because
  595.  *     these are the types of controls that people used on their
  596.  *     color televisions in the old days.
  597.  *
  598.  *     You decide which mode is first used when the ColorWindow is created
  599.  *     by setting the UseRGB argument to TRUE or FALSE.  If TRUE,
  600.  *     the RGB technique will be used.  If FALSE, HSL is used.
  601.  *
  602.  *     But regardless of which technique you specify, the user can switch
  603.  *     to using the other technique by clicking on the RGB / HSL characters
  604.  *     that appear to the left of the proportional gadgets.
  605.  *
  606.  *     On return from this function, this routine returns TRUE if all
  607.  *     went well.  If anything went wrong (usually out of memory) and
  608.  *     the ColorWindow was never created, this routine returns FALSE.
  609.  *
  610.  *     NOTE:  This routine is not re-entrant.  What this means
  611.  *     is that if you have created a program that has more than one task,
  612.  *     this routine cannot be called by more than one task at a time.
  613.  *     This was done for the sake of memory efficiency.
  614.  *     This restriction is not a problem for the grand majority of programs.
  615.  *     But if you have some application that would require calling this
  616.  *     routine asynchronously from multiple tasks, you'll have to
  617.  *     implement some quick semaphore arrangement to avoid collisions.
  618.  *     No big deal, actually.  See Exec semaphores for everything you need.
  619.  *
  620.  *
  621.  * INPUTS
  622.  *     Screen = address of the screen in which the ColorWindow will open.
  623.  *         Can be NULL; if so, the ColorWindow will open in the Workbench
  624.  *     Left = position of the left edge when the ColorWindow opens
  625.  *     Top = position of the top edge when the ColorWindow opens
  626.  *     FirstPen = pen number of the color displayed when the ColorWindow
  627.  *         first opens
  628.  *     UseRGB = TRUE if you want the RGB technique displayed first,
  629.  *         FALSE if you want the HSL technqiue.  See the discussion above
  630.  *
  631.  *
  632.  * RESULT
  633.  *     Returns TRUE if all went well.  If the window couldn't be opened for
  634.  *     any reason, returns FALSE.
  635.  *
  636.  *
  637.  */
  638. BOOL DoColorWindow(screen, left, top, firstpen, usergb)
  639. struct Screen *screen;
  640. SHORT left, top, firstpen;
  641. BOOL usergb;
  642. {
  643.         struct IntuiMessage *message;
  644.         ULONG class;
  645.         struct Gadget *gadget;
  646.         BOOL mousemoved;
  647.         SHORT x, y, code, i;
  648.         struct Remember *key;
  649.         UWORD *ptr;
  650.         BOOL retvalue;
  651.  
  652.         key = NULL;
  653.         retvalue = FALSE;
  654.  
  655.         if (ColorWindow) goto DONE;
  656.  
  657.         ColorNewWindow.LeftEdge = left;
  658.         ColorNewWindow.TopEdge = top;
  659.  
  660.         if (usergb)
  661.                 ColorTemplateGadgets[COLOR_HSL_RGB].Flags &= ~SELECTED;
  662.         else
  663.                 ColorTemplateGadgets[COLOR_HSL_RGB].Flags |= SELECTED;
  664.  
  665.         if ((ptr = (UWORD *)AllocRemember(&key, RGBHSL_SIZE * 2, MEMF_CHIP))
  666.                         == NULL)
  667.                 goto DONE;
  668.         ColorRGBImage.ImageData = ptr;
  669.         for (i = 0; i < RGBHSL_SIZE; i++)
  670.                 *ptr++ = RGBData[i];
  671.         if ((ptr = (UWORD *)AllocRemember(&key, RGBHSL_SIZE * 2, MEMF_CHIP))
  672.                         == NULL)
  673.                 goto DONE;
  674.         ColorHSLImage.ImageData = ptr;
  675.         for (i = 0; i < RGBHSL_SIZE; i++)
  676.                 *ptr++ = HSLData[i];
  677.  
  678.         if (NOT OpenColorWindow(screen, firstpen & 0x3F)) goto DONE;
  679.  
  680.         retvalue = TRUE;
  681.  
  682.         FOREVER
  683.                 {
  684.                 Wait(1 << ColorWindow->UserPort->mp_SigBit);
  685.  
  686.                 mousemoved = FALSE;
  687.                 while (message = GetMsg(ColorWindow->UserPort))
  688.                         {
  689.                         class = message->Class;
  690.                         code = message->Code;
  691.                         gadget = (struct Gadget *)(message->IAddress);
  692.                         x = message->MouseX;
  693.                         y = message->MouseY;
  694.                         ReplyMsg(message);
  695.  
  696.                         switch (class)
  697.                                 {
  698.                                 case GADGETDOWN:
  699.                                 case GADGETUP:
  700.                                         if (ColorGadgetGotten(gadget) == FALSE)
  701.                                                 goto DONE;
  702.                                         break;
  703.                                 case MOUSEMOVE:
  704.                                         mousemoved = TRUE;
  705.                                         break;
  706.                                 case MOUSEBUTTONS:
  707.                                         if (code == SELECTDOWN) ColorWindowHit(x, y);
  708.                                         break;
  709.                                 }
  710.                         }
  711.                 if (mousemoved) ModifyColors();
  712.                 }
  713.  
  714. DONE:
  715.         FreeRemember(&key, TRUE);
  716.         return(retvalue);
  717. }
  718.  
  719.  
  720. /* *** hsl.c ****************************************************************
  721.  *
  722.  * ColorWindow Routine  --  HSL Translation Routines
  723.  *     from Book 1 of the Amiga Programmers' Suite by RJ Mical
  724.  *
  725.  * Copyright (C) 1986, 1987, Robert J. Mical
  726.  * All Rights Reserved.
  727.  *
  728.  * Any or all of this code can be used in any program as long as this
  729.  * entire copyright notice is retained, ok?  Thanks.
  730.  *
  731.  * The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable.
  732.  * All copyright notices and all file headers must be retained intact.
  733.  * The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the
  734.  * resultant object code may be included in any software product.  However, no
  735.  * portion of the source listings or documentation of the Amiga Programmer's
  736.  * Suite Book 1 may be distributed or sold for profit or in a for-profit
  737.  * product without the written authorization of the author, RJ Mical.
  738.  *
  739.  * HISTORY      NAME            DESCRIPTION
  740.  * -----------  --------------  --------------------------------------------
  741.  * 3 Jan 87     RJ >:-{)*       Clean-up for release
  742.  * 27 Feb 86    =RJ Mical=      Modified these routines for Zaphod
  743.  * January 86   =RJ=            Modified the originals for Mandelbrot
  744.  * Late 85      =RJ=            Created the color window for Graphicraft
  745.  *
  746.  * *********************************************************************** */
  747.  
  748.  
  749.  
  750. SHORT HSLToRGB(hue, saturation, luminance)
  751. USHORT hue, saturation, luminance;
  752. /* This actually doesn't do true HSL to RGB conversion, but it works
  753.  * close enough.  Also, this code could be optimized quite a bit, but
  754.  * I've left it spread out like this so that several years from now
  755.  * I will be able to figure out what the heck is going on.
  756.  */
  757. {
  758.         LONG red, green, blue;
  759.         LONG reddiff, greendiff, bluediff;
  760.         LONG sixth, rising, falling, invertsaturation;
  761.  
  762.         /* We're going to hold one color off, a second at full, and ramp
  763.          * the third.  This allows us to visit all two-color combinations.
  764.          * By modifying saturation, all three-color combinations can be seen.
  765.          */
  766.         sixth = hue / 0x2AAB;
  767.         rising = (hue - (sixth * 0x2AAB)) * 6;
  768.         falling = 0xFFFF - rising;
  769.  
  770.         switch (sixth)
  771.                 {
  772.                 case 0:
  773.                         red = 0xFFFF;
  774.                         green = rising;
  775.                         blue = 0;
  776.                         break;
  777.                 case 1:
  778.                         red = falling;
  779.                         green = 0xFFFF;
  780.                         blue = 0;
  781.                         break;
  782.                 case 2:
  783.                         red = 0;
  784.                         green = 0xFFFF;
  785.                         blue = rising;
  786.                         break;
  787.                 case 3:
  788.                         red = 0;
  789.                         green = falling;
  790.                         blue = 0xFFFF;
  791.                         break;
  792.                 case 4:
  793.                         red = rising;
  794.                         green = 0;
  795.                         blue = 0xFFFF;
  796.                         break;
  797.                 case 5:
  798.                         red = 0xFFFF;
  799.                         green = 0;
  800.                         blue = falling;
  801.                         break;
  802.                 }
  803.  
  804.         red = (red * luminance) >> 16;
  805.         green = (green * luminance) >> 16;
  806.         blue = (blue * luminance) >> 16;
  807.  
  808.         /* The closer saturation is to zero, the closer red, green and blue should
  809.          * be to luminance.
  810.          */
  811.         invertsaturation = 0xFFFF - saturation;
  812.         reddiff = luminance - red;
  813.         red = red + ((reddiff * invertsaturation) >> 16);
  814.         greendiff = luminance - green;
  815.         green = green + ((greendiff * invertsaturation) >> 16);
  816.         bluediff = luminance - blue;
  817.         blue = blue + ((bluediff * invertsaturation) >> 16);
  818.  
  819.         red = (red >> 12) & 0xF;
  820.         green = (green >> 12) & 0xF;
  821.         blue = (blue >> 12) & 0xF;
  822.  
  823.         return( (SHORT)((red << 8) | (green << 4) | (blue)) );
  824. }
  825.  
  826.  
  827.  
  828. VOID RGBToHSL(rgb, returnhue, returnsat, returnlum)
  829. USHORT rgb;
  830. USHORT *returnhue, *returnsat, *returnlum;
  831. {
  832.         LONG min, max, hue, saturation, luminance, differential;
  833.         LONG redpart, greenpart, bluepart;
  834.         LONG workred, workgreen, workblue;
  835.  
  836.         workred = ((rgb >> 8) & 0xF) * 0x111;
  837.         workgreen = ((rgb >> 4) & 0xF) * 0x111;
  838.         workblue = (rgb & 0xF) * 0x111;
  839.  
  840.         if (workred < workgreen) min = workred;
  841.         else min = workgreen;
  842.         if (workblue < min) min = workblue;
  843.  
  844.         if (workred > workgreen) max = workred;
  845.         else max = workgreen;
  846.         if (workblue > max) max = workblue;
  847.  
  848.         luminance = max;
  849.         luminance <<= 4;
  850.         differential = max - min;
  851.  
  852.         if (max != 0)
  853.                 {
  854.                 saturation = (differential << 16) / max;
  855.                 if (saturation > 0xFFFF) saturation = 0xFFFF;
  856.                 }
  857.         else
  858.                 saturation = 0;
  859.  
  860.         if (saturation == 0)
  861.                 hue = 0;
  862.         else
  863.                 {
  864.                 redpart = (((max - workred) << 16) / differential) >> 4;
  865.                 greenpart = (((max - workgreen) << 16) / differential) >> 4;
  866.                 bluepart = (((max - workblue) << 16) / differential) >> 4;
  867.  
  868.                 if (workred == max) hue = bluepart - greenpart;
  869.                 else if (workgreen == max) hue = 0x2000 + redpart - bluepart;
  870.                 else if (workblue == max) hue = 0x4000 + greenpart - redpart;
  871.                 if (hue < 0) hue += 0x6000;
  872.                 hue = (hue * 2667) / 1000;
  873.                 }
  874.  
  875.         *returnhue = hue;
  876.         *returnsat = saturation;
  877.         *returnlum = luminance;
  878. }
  879.  
  880.  
  881.  
  882.  
  883.  
  884.  
  885.